<template>
    <div>
        <h2>公司关系网络图示例</h2>
        <div id="company-graph" style="width:100%;height:800px;background:#f5f5f5;"></div>
    </div>
</template>
<script setup lang="ts">
defineOptions({ name: 'AntvG6CompanyRelation' });
const FontSize = 16;
import { onMounted } from 'vue';
import { Graph } from '@antv/g6';
const palette = [
    '#5B8FF9', '#5AD8A6', '#F6BD16', '#E8684A', '#6DC8EC',
    '#9270CA', '#FF9D4D', '#269A99', '#FF99C3', '#A9A9A9'
];
// 计算节点size（直径），根据文本长度和换行数自适应
function calcNodeSize(label: string, fontSize = FontSize, padding = 32, maxLineLen = 8, maxLines = 3) {
    // 按maxLineLen分行，最多maxLines行
    const lines = [];
    let i = 0;
    // 将label处理成多行
    while (i < label.length && lines.length < maxLines) {
        lines.push(label.slice(i, i + maxLineLen));
        i += maxLineLen;
    }
    if (i < label.length) {
        lines[lines.length - 1] += '…';
    }
    const maxLineWidth = Math.max(...lines.map(line => line.length));
    // 估算宽度 = 最大行字符数 * 字体宽度 + padding
    const width = maxLineWidth * fontSize - 20;
    // 估算高度 = 行数 * 字体高度 + padding
    const height = lines.length * fontSize * 1.2 + padding;
    // 圆形节点取宽高最大值为直径
    return {
        label: lines.join('\n'),
        size: Math.max(width, height)
    };
}

onMounted(() => {
    // 构造公司关系数据
    // 新增500个模拟节点
    const mockNodes = Array.from({ length: 400 }).map((_, i) => ({
        id: `mock${i}`,
        label: `模拟公司${i}号节点-测试内容`,
    }));
    // 预处理节点，计算size和换行label
    const nodes = mockNodes.map((d, i) => {
        const { label, size } = calcNodeSize(d.label, 16, 32, 8, 3);
        return {
            id: d.id,
            label,
            size,
            style: {
                fill: palette[i % palette.length],
                labelText: label,
                labelPlacement: 'center',
                fontSize: FontSize,
                size: size,
                labelTextFill: '#fff',
                labelTextAlign: 'center',
                labelTextBaseline: 'middle',
                // stroke: '#fff',
                // lineWidth: 1,
                // strokeOpacity: 0.8
            }
            // style: { ...defaultStyle },
        };
    });
    console.log('nodes', nodes);
    // 原有边
    const baseEdges = [
        {
            source: 'center',
            target: 'n1',
            label: '强协',
            style: {
                stroke: '#1890ff',
                lineWidth: 2,
                startArrow: { path: 'M 10,0 L 0,5 L 10,10 Z', fill: '#1890ff' },
                endArrow: { path: 'M 10,0 L 0,5 L 10,10 Z', fill: '#1890ff' },
            },
        },
        {
            source: 'center',
            target: 'n2',
            label: '合作',
            style: {
                stroke: '#fa541c',
                lineWidth: 2,
                startArrow: { path: 'M 10,0 L 0,5 L 10,10 Z', fill: '#fa541c' },
                endArrow: { path: 'M 10,0 L 0,5 L 10,10 Z', fill: '#fa541c' },
            },
        },
        {
            source: 'center',
            target: 'n3',
            label: '功率',
            style: {
                stroke: '#fa541c',
                lineWidth: 2,
                startArrow: { path: 'M 10,0 L 0,5 L 10,10 Z', fill: '#fa541c' },
                endArrow: { path: 'M 10,0 L 0,5 L 10,10 Z', fill: '#fa541c' },
            },
        },
        {
            source: 'center',
            target: 'n4',
            label: '合作',
            style: {
                stroke: '#fa541c',
                lineWidth: 2,
                startArrow: { path: 'M 10,0 L 0,5 L 10,10 Z', fill: '#fa541c' },
                endArrow: { path: 'M 10,0 L 0,5 L 10,10 Z', fill: '#fa541c' },
            },
        },
    ];
    // 新增模拟边：每个mock节点与前3个mock节点和center相连
    const mockEdges = [];
    const mockEdgeStyle = {
        lineWidth: 1,
        labelPlacement: 'center',      // 显式指定文本在边中间
        // labelBackgroundFill: '#f5f5f5', // 标签背景色
        // labelBackground: true, // 显示标签背景
        // labelPadding: [4, 2],
        endArrow: true,
    };
    for (let i = 0; i < mockNodes.length; i++) {
        // 与center连一条
        
        // mockEdges.push({ source: 'center', target: `mock${i}`, label: '模拟关联', style: style });
        // 与前3个mock节点连（避免自环和重复）
        for (let j = 1; j <= 3; j++) {
            if (i - j >= 0) {
                const label = `模拟边${j}`;
                const style = {
                    ...mockEdgeStyle,
                    stroke: nodes[i].style.fill,
                    labelText: label
                };
                mockEdges.push({ source: `mock${i}`, target: `mock${i - j}`, label, style: style });
            }
        }
    }
    // 合并所有边
    const edges = mockEdges;
    console.log('edges', edges);
    const data = {
        nodes,
        edges,
    };

    // 创建 G6 图实例
    const graph = new Graph({
        container: 'company-graph',
        width: 1200,
        height: 800,
        data: data as any,
        // node: {
        //     type: 'circle',
        //     style: {
        //         labelText: (d: any) => d.label,
        //         labelPlacement: 'center',
        //         fontSize: FontSize,
        //         size: (d: any) => d.size,
        //         labelTextFill: '#fff',
        //         labelTextAlign: 'center',
        //         labelTextBaseline: 'middle',
        //         fill: (d: any) => d.style?.fill,
        //         // fill: 'red',
        //         stroke: '#fff',
        //         lineWidth: 1,
        //         strokeOpacity: 0.8
        //     },
        // },
        // edge: {
        //     style: {
        //         labelText: (d: any) => d.label,
        //         stroke: (d: any) => d.style?.stroke,
        //         lineWidth: (d: any) => d.style?.lineWidth,
        //         labelPlacement: 'center',      // 显式指定文本在边中间
        //         labelBackgroundFill: '#f5f5f5', // 标签背景色
        //         labelBackground: true, // 显示标签背景
        //         labelPadding: [4, 2],
        //         endArrow: true,
        //     },
        // },
        layout: {
            type: 'random',
            // center: [600, 400],
            // radius: 300,
            // startAngle: 0,
            // endAngle: 2 * Math.PI,
            // ordering: 'topology',
        },
        behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],
    });

    graph.render();
});
</script> 